{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Bit Reader\n",
    "Encode/Decode a set of bits"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Initializes with parameter `options`, which must be a dictionary with the following format:\n",
    "\n",
    "- keys must be a str with the bits places, example: '0-1' means bit 0 and bit 1\n",
    "\n",
    "- values must be a dictionary with the bit value as the key and the category (str) as value. Categories must be unique.\n",
    "\n",
    "- Encode: given a category/categories return a list of possible values\n",
    "- Decode: given a value return a list of categories"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Example\n",
    "\n",
    "MOD09 (http://modis-sr.ltdri.org/guide/MOD09_UserGuide_v1_3.pdf)\n",
    "(page 28, state1km, 16 bits):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ee\n",
    "ee.Initialize()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from geetools import bitreader"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = {\n",
    " '0-1': {0:'clear', 1:'cloud', 2:'mix'},  # cloud state\n",
    " '2-2': {0: 'no_shadow', 1:'shadow'},  # cloud shadow (bit 0 is not needed)\n",
    " '6-7': {0:'climatology', 1:'low', 2:'average', 3:'high'}  # land/water flag\n",
    " }"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "reader = bitreader.BitReader(options, 16)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Internally it computes a dict with\n",
    "- bit_length (length of the group of bits)\n",
    "- lshift (left shift)\n",
    "- shifted (shifted places)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'average': {'bit_length': 2, 'lshift': 6, 'shifted': 2},\n",
       " 'clear': {'bit_length': 2, 'lshift': 0, 'shifted': 0},\n",
       " 'climatology': {'bit_length': 2, 'lshift': 6, 'shifted': 0},\n",
       " 'cloud': {'bit_length': 2, 'lshift': 0, 'shifted': 1},\n",
       " 'high': {'bit_length': 2, 'lshift': 6, 'shifted': 3},\n",
       " 'low': {'bit_length': 2, 'lshift': 6, 'shifted': 1},\n",
       " 'mix': {'bit_length': 2, 'lshift': 0, 'shifted': 2},\n",
       " 'no_shadow': {'bit_length': 1, 'lshift': 2, 'shifted': 0},\n",
       " 'shadow': {'bit_length': 1, 'lshift': 2, 'shifted': 1}}"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.info"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "bit length 16\n"
     ]
    }
   ],
   "source": [
    "print('bit length', reader.bit_length)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "DECODE ONE VALUE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "204: 11001100\n"
     ]
    }
   ],
   "source": [
    "value = 204\n",
    "bits = reader.getBin(value)\n",
    "print('204:', bits)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['shadow', 'clear', 'high']"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.decode(204)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "MATCH ONE VALUE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "False"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.match(204, 'cloud')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.match(204, 'shadow')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ENCODE A VALUE (EXCLUSIVELLY)\n",
    "\n",
    "In this case, shadow is 00000100 (4) and **not** 00000101 (5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.encode('shadow')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.encode('clear')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reader.encode('no_shadow')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ENCODE A VALUE (ALL)\n",
    "\n",
    "This will get **all** values (all combinations where the bit is set)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 23, 28, 29, 30, 31, 36, 37, 38, 39, 44, 45, 46, 47, 52, 53, 54, 55, 60, 61, 62, 63, 68, 69, 70, 71, 76, 77, 78, 79, 84, 85, 86, 87, 92, 93, 94, 95, 100, 101, 102, 103, 108, 109, 110, 111, 116, 117, 118, 119, 124, 125, 126, 127, 132, 133, 134, 135, 140, 141, 142, 143, 148, 149, 150, 151, 156, 157, 158, 159, 164, 165, 166, 167, 172, 173, 174, 175, 180, 181, 182, 183, 188, 189, 190, 191, 196, 197, 198, 199]\n"
     ]
    }
   ],
   "source": [
    "print(reader.encodeOne('shadow')[0:100])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93, 97, 101, 105, 109, 113, 117, 121, 125, 129, 133, 137, 141, 145, 149, 153, 157, 161, 165, 169, 173, 177, 181, 185, 189, 193, 197, 201, 205, 209, 213, 217, 221, 225, 229, 233, 237, 241, 245, 249, 253, 257, 261, 265, 269, 273, 277, 281, 285, 289, 293, 297, 301, 305, 309, 313, 317, 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 365, 369, 373, 377, 381, 385, 389, 393, 397]\n"
     ]
    }
   ],
   "source": [
    "print(reader.encodeOne('cloud')[0:100])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "ENCODE AND"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[5, 13, 21, 29, 37, 45, 53, 61, 69, 77, 85, 93, 101, 109, 117, 125, 133, 141, 149, 157, 165, 173, 181, 189, 197, 205, 213, 221, 229, 237, 245, 253, 261, 269, 277, 285, 293, 301, 309, 317, 325, 333, 341, 349, 357, 365, 373, 381, 389, 397, 405, 413, 421, 429, 437, 445, 453, 461, 469, 477, 485, 493, 501, 509, 517, 525, 533, 541, 549, 557, 565, 573, 581, 589, 597, 605, 613, 621, 629, 637, 645, 653, 661, 669, 677, 685, 693, 701, 709, 717, 725, 733, 741, 749, 757, 765, 773, 781, 789, 797]\n"
     ]
    }
   ],
   "source": [
    "print(reader.encodeAnd('cloud', 'shadow')[0:100])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### DECODE AN IMAGE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import ee"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [],
   "source": [
    "from geetools import ui, cloud_mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "595b6cdff8534eb1a6d9c280dc2fd5e2",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Map(basemap={'max_zoom': 19, 'url': 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', 'attribution': 'Map …"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "c0339add428a4ce980e0a22ec3267e41",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Tab(children=(CustomInspector(children=(SelectMultiple(options=OrderedDict(), value=()), Accordion(selected_in…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "Map = ui.Map()\n",
    "Map.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "modcol = ee.ImageCollection('MODIS/006/MOD09GA').sort('system:time_start', False)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [],
   "source": [
    "mod = ee.Image(modcol.first())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "BANDS"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [],
   "source": [
    "red = 'sur_refl_b01'\n",
    "green = 'sur_refl_b04'\n",
    "blue = 'sur_refl_b03'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [],
   "source": [
    "qa = 'state_1km'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [],
   "source": [
    "qa_mask = mod.select(qa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [],
   "source": [
    "Map.addLayer(mod, {'bands':[red, green, blue], 'min':0, 'max':5000}, 'Original')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [],
   "source": [
    "Map.addLayer(qa_mask, {'min':0, 'max':reader.max}, 'QA')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "APPLY THE `BitReader` TO THE BAND THAT HOLDS THE BIT INFORMATION"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [],
   "source": [
    "mask = reader.decodeImage(mod, qa)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [],
   "source": [
    "Map.addLayer(mask.select(['cloud']), {'min':0, 'max':1}, 'Clouds')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`BitReader` INFORMATION FOR KNOW COLLECTIONS AVAILABLE IN `geetools.cloud_mask` MODULE"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [],
   "source": [
    "from geetools import cloud_mask"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "outputs": [],
   "source": [
    "state1km = cloud_mask.BITS_MODIS09GA"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'0-1': {0: 'clear', 1: 'cloud', 2: 'mix'},\n",
       " '13': {1: 'adjacent'},\n",
       " '15': {1: 'snow'},\n",
       " '2': {1: 'shadow'},\n",
       " '8-9': {1: 'small_cirrus', 2: 'average_cirrus', 3: 'high_cirrus'}}"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "state1km"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
